-- Table
-- Create by weism
-- 扩展table的函数库

-- 合并两个没有顺序的table
function table.add(a, b)
    local r = {};
    for k, v in pairs(a) do
        r[k] = v;
    end
    for k, v in pairs(b) do
        r[k] = v;
    end
    return r;
end

-- 连接两个有顺序的table
function table.append(a, b)
    local r = {};
    for i = 1, #a do
        table.insert(r, a[i]);
    end
    for i = 1, #b do
        table.insert(r, b[i]);
    end
    return r;
end

-- 查找元素
function table.indexOf(t, item)
    for i = 1, #t do
        if t[i] == item then
            return i;
        end
    end

    return -1;
end

-- 分片
function table.slice(t, s, e)
    local ret = {};

    -- 默认是到结束
    e = e or #t;

    for i = s, e do
        if not t[i] then
            break;
        end

        table.insert(ret, t[i]);
    end

    return ret;
end

-- 删除指定元素
function table.removeItem(t, item)
    local at = table.indexOf(t, item);

    if at > 0 then
        table.remove(t, at);
    end

    return at;
end

-- 随便选择一个key值
function table.randomKey(t)
    local keys = {};
    for k, _ in pairs(t) do
        table.insert(keys, k);
    end

    return keys[math.random(1, #keys)];
end

-- 随便选择一个value值
function table.randomValue(t)
    local values = {};
    for _, v in pairs(t) do
        table.insert(values, v);
    end

    return values[math.random(1, #values)];
end

-- 拷贝一个表
function table.deepcopy(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

-- 复制一个table
function table.copy(t)
    if (type(t) ~= "table") then
        return t;
    end

    local new_t = {};
    for k, v in pairs(t) do
        new_t[k] = v;
    end
    return new_t;
end

--将table的关键字取出，构造数组返回
function table.keys(t)
    local keys = {};
    for k, _ in pairs(t) do
        table.insert(keys, k);
    end

    return keys;
end

--将table中值对的关键字对应的值构造数组返回
function table.values(t)
    local values = {};
    for _, v in pairs(t) do
        table.insert(values, v);
    end

    return values;
end

-- 将table中的元素随机排序
function table.randomSort(t)
    local num = #t;
    -- 洗三遍
    for round = 1, 3 do
        for i = 1, num-1 do
            -- 和随机一个其他的交换
            local swapIndex = math.random(i+1, num);
            local tmp = t[swapIndex];
            t[swapIndex] = t[i];
            t[i] = tmp;
        end
    end
end

-- table的key中最大数，key需要全部都是number
function table.maxKey(t)
    local ret;
    for k, _ in pairs(t) do
        if not ret or ret < k then
            ret = k;
        end
    end

    return ret;
end

-- table的value中的最大数，需要确保value全部都是number
function table.maxValue(t)
    local ret;
    for _, v in pairs(t) do
        if not ret or ret < v then
            ret = v;
        end
    end

    return ret;
end

-- 还原table
function table.restoreTable(t)
    if type(t) ~= "table" then
        return t;
    end

    local v = t;
    if t.array then
        v = t:toTable();
    end

    local ret = {};
    for key, value in pairs(v) do
        ret[key] = table.restoreTable(value);
    end

    return ret;
end

-- 返回只读的table
function table.readOnly(t)
    return setmetatable({}, {
        __index = t,
        __newindex = function(table, key, value)
            error("Attempt to modify read-only table")
        end,
        __metatable = false
    });
end

-- table是否相等
function table.equal(a, b, depth)
    -- 默认10层，避免死循环
    depth = depth or 10;

    if a == b then
        return true;
    end

    if depth <= 0 then
        return true;
    end

    -- 不是table，不用比了，上面的a == b就得出结果了
    if type(a) ~= "table" or type(b) ~= "table" then
        return false;
    end

    local checkKeys = {};
    for key, v in pairs(a) do
        if not table.equal(v, b[key], depth - 1) then
            return false;
        end

        checkKeys[key] = true;
    end

    for key, v in pairs(b) do
        if not checkKeys[key] and not table.equal(v, a[key], depth - 1) then
            return false;
        end
    end

    return true;
end

-- 打开并返回table的对象
function table.unpack(t, i)
    i = i or 1;
    if i == table.getn(t) then
        return t[i];
    elseif i > table.getn(t) then
        return nil;
    end
    return t[i], table.unpack(t, i + 1);
end
